package cn.itwen.star.graph.core.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;

import cn.itwen.star.graph.comfyui.client.pojo.ComfyuiModel;
import cn.itwen.star.graph.comfyui.client.pojo.ComfyuiRequestDto;
import cn.itwen.star.graph.comfyui.client.pojo.ComfyuiTask;
import cn.itwen.star.graph.core.dto.request.Text2ImageReqDto;
import cn.itwen.star.graph.core.dto.respone.CanelTaskResDto;
import cn.itwen.star.graph.core.dto.respone.Text2ImageResDto;
import cn.itwen.star.graph.core.service.*;
import cn.itwen.star.graph.core.utils.UserUtils;
import com.alibaba.fastjson2.JSON;
import freemarker.template.TemplateException;
import io.lettuce.core.RedisBusyException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;


@Service
@Slf4j
public class Text2ImageServiceImpl implements Text2ImageService {

    public static final String COMFYUI_CLIENT_ID = "star-graph";

    @Autowired
    private OllamaService ollamaService;

    @Autowired
    private FreemarkerService freemarkerService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private UserFundRecordService userFundRecordService;

    @Autowired
    private UserFundService userFundService;


    /**
     * 将前端传递的生成图参数封装为redis中的任务对象
     * @param reqDto 前端传递的生成图参数
     * @return redis中的任务对象（包含了comffyui的任务·对象）
     */
    public ComfyuiTask getComfyuiTask(Text2ImageReqDto reqDto) throws TemplateException, IOException {
        //1. 将text2ImageReqDto转换成ComfyuiModel
        //基本参数封装
        ComfyuiModel model = BeanUtil.toBean(reqDto, ComfyuiModel.class);
        model.setWidth(reqDto.width());
        model.setHeight(reqDto.height());
        model.setModelName(reqDto.modelName());
        model.setSamplerName(reqDto.samplerName());
        model.setScheduler(reqDto.scheduler());
        //封装提示词与负向提示词
        model.setPropmt(String.format("(8k, best quality, masterpiece),(high detailed skin),%s", ollamaService.translate(model.getPropmt())));
        if (StrUtil.isNotEmpty(model.getReverse())) {
            model.setReverse(ollamaService.translate(model.getReverse()));
        }
        model.setReverse(String.format("%s,bad face,naked,bad finger,bad arm,bad leg,bad eye", model.getReverse()));

        //2. 利用ComfyuiModel结合模板使用Freemarker渲染出comfyui json
        String prompt = freemarkerService.renderText2Image(model);
        //3. 构建出Comfyui生图需要的对象ComfyuiRequestDto
        Object promptObj = JSON.parseObject(prompt, Object.class);
        ComfyuiRequestDto requestDto = ComfyuiRequestDto.builder()
                .clientId(COMFYUI_CLIENT_ID)
                .prompt(promptObj)
                .build();
        //4. 构建出ComfyuiTask（Redis任务对象）
        ComfyuiTask task = new ComfyuiTask(reqDto.getClientId(), requestDto);
        task.setSize(reqDto.getSize());
        return task;
    }

    @Override
    public Text2ImageResDto propmt(Text2ImageReqDto text2ImageReqDto) throws TemplateException, IOException {
        //0.积分冻结
        userFundRecordService.pointsFreeze(UserUtils.getUser().getId(), text2ImageReqDto.getSize());
        //1.获取comfyuiTask对象
        ComfyuiTask comfyuiTask = getComfyuiTask(text2ImageReqDto);
        //封装用户id
        comfyuiTask.setUserId(UserUtils.getUser().getId());
        //2.添加任务数据到redis中
        comfyuiTask = redisService.addQueueTask(comfyuiTask);
        //3.返回结果
        Text2ImageResDto text2ImageResDto = new Text2ImageResDto();
        text2ImageResDto.setPid(comfyuiTask.getId());
        text2ImageResDto.setQueueIndex(comfyuiTask.getIndex());
        return text2ImageResDto;
    }

    @Override
    public String canel(CanelTaskResDto canelTaskResDto) {
        ComfyuiTask comfyuiTask = redisService.cancelTask(canelTaskResDto.getTempId());
        if (comfyuiTask ==  null){
            throw new RedisBusyException("任务已经开始，不能取消任务");
        }
        try {
            //归还冻结积分
            userFundRecordService.freezeReturn(UserUtils.getUser().getId(),comfyuiTask.getSize());
        }catch (Exception e){
            log.error("积分归还失败:{}",canelTaskResDto.getTempId());
            //积分归还失败,则重新把任务放在队列中
            redisService.returnTask(comfyuiTask,canelTaskResDto.getIndex());
        }
        return "取消成功";
    }

    @Override
    public Long proprity(CanelTaskResDto canelTaskResDto) {
        // 划扣积分
        userFundRecordService.directDeduction(UserUtils.getUser().getId(), 5);
        Long newIndex = redisService.proprityTask(canelTaskResDto.getTempId());
        if(newIndex==null){
            userFundRecordService.deductionReturnScore(UserUtils.getUser(), 5);
        }
        return newIndex;
    }
}